package com.xyrl.project.app.controller.csr;


import com.aliyuncs.dypnsapi.model.v20170525.GetMobileResponse;
import com.xyrl.common.base.exception.XyrlException;
import com.xyrl.common.util.IpAddrUtil;
import com.xyrl.common.util.ObjectUtil;
import com.xyrl.common.util.RedisUtil;
import com.xyrl.common.util.StringUtil;
import com.xyrl.project.common.authentication.LoginInfo;
import com.xyrl.project.common.base.service.CacheService;
import com.xyrl.project.common.base.vo.ResponseData;
import com.xyrl.project.common.common.service.AppService;
import com.xyrl.project.common.constant.DictConstant;
import com.xyrl.project.common.constant.XyrlConstant;
import com.xyrl.project.common.csr.service.CsrUserService;
import com.xyrl.project.common.csr.vo.CsrLoginVo;
import com.xyrl.project.common.csr.vo.CsrUserVo;
import com.xyrl.project.common.domian.MsgCodeVo;
import com.xyrl.project.common.log.enu.SmsSendType;
import com.xyrl.project.common.log.service.SmsSendLogService;
import com.xyrl.project.common.store.enu.StoreStatus;
import com.xyrl.project.common.store.service.StoreService;
import com.xyrl.project.common.store.vo.StoreVo;
import com.xyrl.project.common.system.entity.LoginLog;
import com.xyrl.project.common.system.service.DictionaryService;
import com.xyrl.project.common.system.service.LoginLogService;
import com.xyrl.project.common.util.CheckDeviceUtil;
import com.xyrl.third.aliyun.constant.AliYunConstant;
import com.xyrl.third.aliyun.service.MobileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.asm.Advice;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

/**
 * 客户端登录与登出
 *
 * @author zhongp
 * @version 1.0
 * @className CustomerLoginController
 * @company 星纭融链科技服务有限公司
 * @date 2020-01-02 11:44:01
 * @Description
 */
@RestController
@RequestMapping("/csr/login")
@Api(value = "登录", tags = "客户登录")
@Slf4j
public class CsrLoginController {

    @Autowired
    private CsrUserService csrUserService;
    @Autowired
    private StoreService storeService;
    @Autowired
    private SmsSendLogService smsSendLogService;
    @Autowired
    private LoginLogService loginLogService;
    @Autowired
    private CacheService cacheService;
    @Autowired
    private MobileService mobileService;
    @Autowired
    private AppService appService;
    @Autowired
    private DictionaryService dictionaryService;


    @ApiOperation("登录")
    @PostMapping
    public ResponseData login(HttpServletRequest request, @Valid CsrLoginVo csrLoginVo, @RequestHeader("user-agent") String userAgent) {
        String ip = IpAddrUtil.getIpAddr(request);
        String errorMsg = "";
        try {
            checkVerificationCode(csrLoginVo);
            CsrUserVo user = login(ip, csrLoginVo.getMobile(), userAgent);

            return ResponseData.success(user);
        } catch (XyrlException e) {
            errorMsg = e.getMessage();
        } catch (Exception e) {
            errorMsg = e.getMessage();
        }
        return ResponseData.error(errorMsg);
    }

    /**
     * 发送短信
     *
     * @param mobile 接收手机号
     * @return
     * @throws XyrlException
     */
    @ApiOperation("发送短信验证码")
    @PostMapping("sendMsg")
    public ResponseData sendMsg(String mobile) throws XyrlException {
        String templateId = XyrlConstant.SMS_LOGIN_TEMPLATE_ID;
        smsSendLogService.sendSmsVerificationCode(mobile, templateId, SmsSendType.loginCode.getValue());
        return ResponseData.success();
    }

    /**
     * 根据token 取得手机号码
     *
     * @param token
     * @return
     */
    @ApiOperation("一键登录")
    @PostMapping("oneClickLogin")
    public ResponseData oneClickLogin(HttpServletRequest request, String token, @RequestHeader("user-agent") String userAgent) {
        GetMobileResponse response = mobileService.getMobile(token);
        String ip = IpAddrUtil.getIpAddr(request);
        //成功
        if (AliYunConstant.ALI_YUN_RTN_SUCCESS.equalsIgnoreCase(response.getCode())) {
            try {
                return ResponseData.success(login(ip, response.getGetMobileResultDTO().getMobile(), userAgent));
            } catch (XyrlException e) {
                return ResponseData.error(e.getMessage());
            }
        } else {
            return ResponseData.error(response.getMessage());
        }
    }
    @ApiOperation("客户退出登录")
    @PostMapping("loginOut")
    public ResponseData loginOut() {
        // 取得登录token 值
        String token = (String) SecurityUtils.getSubject().getPrincipal();
        cacheService.clearCacheLoginUser(token);
        return ResponseData.success("退出成功");
    }
    /**
     * 用户登录操作
     *
     * @param ip        访问ip
     * @param mobile    手机号
     * @param userAgent 调备类型
     * @return
     * @throws XyrlException
     */
    private CsrUserVo login(String ip, String mobile, String userAgent) throws XyrlException {
        LoginLog loginLog = new LoginLog();
        loginLog.setDeviceType(CheckDeviceUtil.getDevice(userAgent));
        loginLog.setDevice(userAgent);
        loginLog.setIp(ip);
        loginLog.setUsername(mobile);
        try {
            CsrUserVo user = csrUserService.loginByCsr(mobile);
            StoreVo storeVo = storeService.findByCsrUserId(user.getId());
            if (null != storeVo) {
                BeanUtils.copyProperties(storeVo,user);
                user.setStoreId(storeVo.getId());
            }
            //登录用户id
            loginLog.setUserId(user.getId());
            LoginInfo info = new LoginInfo(user.getMobile(), XyrlConstant.USER_TYPE_CUSTOMER);
            //缓存用户登录信息
            cacheService.cacheLoginUser(ip, info, user.getToken());

            // 查询客户电话
            String servicePhone = dictionaryService.findValueByKey(DictConstant.SERVICE_PHONE);
            //添加客户电话
            user.setServicePhone(servicePhone);

            user.setAppConfigVo(appService.getAppConfig());
            return user;
        } catch (XyrlException e) {
            loginLog.setLoginResponse(e.getMessage());
            throw e;
        } finally {
            // 保存登录记录
            loginLogService.saveLoginLog(loginLog);
        }
    }


    /**
     * 手机短信验证码校验
     *
     * @param csrLoginVo
     * @throws XyrlException
     */
    private void checkVerificationCode(CsrLoginVo csrLoginVo) throws XyrlException {
        String cacheKey = StringUtil.concat(SmsSendType.loginCode.getValue(), ":", csrLoginVo.getMobile());
        String codeKey = StringUtil.concat(XyrlConstant.ALIYUN_SMS_VALID_TERM, cacheKey);
        //判断短信验证码是否失效
        if (!RedisUtil.hasKey(codeKey)) {
            throw new XyrlException("验证码己过期，请重新发送");
        }
        try {
            //短信验证码是否正确
            MsgCodeVo vo = RedisUtil.getData(codeKey, MsgCodeVo.class);
            if (ObjectUtil.isNotEmpty(vo)) {
                //知信验证码与手机号是否匹配
                if (!vo.getMobile().equalsIgnoreCase(csrLoginVo.getMobile()) || !vo.getCode().equalsIgnoreCase(csrLoginVo.getCode())) {
                    throw new XyrlException("验证码错误.");
                }
                //删除该验证码级存信息
                RedisUtil.delKey(codeKey);
            } else {
                throw new XyrlException("验证码己过期，请重新发送");
            }
        } catch (Exception e) {
            throw new XyrlException("验证码错误.");
        }

    }

}
